#include "Int_LCD.h"
#include "Int_LCD_Font.h"
#include <stdbool.h>
#include "dma.h"

#define Delay_ms(x) HAL_Delay(x)


void Int_LCD_Init(void)
{
    // 1.��ʼ��FSMC
//    MX_FSMC_Init();

    // 2.��λ
    Int_LCD_Rest();

    // 3.��������
    Int_LCD_BGOn();

    // 4.����LCD�Ĵ���
    Int_RegCconfig();
}

void Int_LCD_Rest(void)
{
    // GPIOG->ODR &= ~GPIO_ODR_ODR15;
    HAL_GPIO_WritePin(LCD_RES_GPIO_Port,LCD_RES_Pin,GPIO_PIN_RESET);

    Delay_ms(50);

    // GPIOG->ODR |= GPIO_ODR_ODR15;
    HAL_GPIO_WritePin(LCD_RES_GPIO_Port,LCD_RES_Pin,GPIO_PIN_SET);

    Delay_ms(50);
}

void Int_LCD_BGOn(void)
{
    // GPIOB->ODR |= GPIO_ODR_ODR0;
    HAL_GPIO_WritePin(LCD_BG_GPIO_Port,LCD_BG_Pin,GPIO_PIN_SET);
}

void Int_LCD_BGOff(void)
{
    // GPIOB->ODR &= ~GPIO_ODR_ODR0;
    HAL_GPIO_WritePin(LCD_BG_GPIO_Port,LCD_BG_Pin,GPIO_PIN_RESET);
}

void Int_LCD_WriteCmd(uint16_t cmd)
{
    *LCD_ADDR_CMD = cmd;
}

void Int_LCD_WriteData(uint16_t data)
{
    *LCD_ADDR_DATA = data;
}

uint16_t Int_LCD_ReadData(void)
{
    return *LCD_ADDR_DATA;
}

void Int_RegCconfig(void)
{
    /* 1. ���ûҽ׵�ѹ�Ե���TFT����٤�����ԣ� ��У׼��һ����������ú��� */
    Int_LCD_WriteCmd(0xE0);
    Int_LCD_WriteData(0x00);
    Int_LCD_WriteData(0x07);
    Int_LCD_WriteData(0x10);
    Int_LCD_WriteData(0x09);
    Int_LCD_WriteData(0x17);
    Int_LCD_WriteData(0x0B);
    Int_LCD_WriteData(0x41);
    Int_LCD_WriteData(0x89);
    Int_LCD_WriteData(0x4B);
    Int_LCD_WriteData(0x0A);
    Int_LCD_WriteData(0x0C);
    Int_LCD_WriteData(0x0E);
    Int_LCD_WriteData(0x18);
    Int_LCD_WriteData(0x1B);
    Int_LCD_WriteData(0x0F);

    /* 2. ���ûҽ׵�ѹ�Ե���TFT����٤�����ԣ���У׼ */
    Int_LCD_WriteCmd(0XE1);
    Int_LCD_WriteData(0x00);
    Int_LCD_WriteData(0x17);
    Int_LCD_WriteData(0x1A);
    Int_LCD_WriteData(0x04);
    Int_LCD_WriteData(0x0E);
    Int_LCD_WriteData(0x06);
    Int_LCD_WriteData(0x2F);
    Int_LCD_WriteData(0x45);
    Int_LCD_WriteData(0x43);
    Int_LCD_WriteData(0x02);
    Int_LCD_WriteData(0x0A);
    Int_LCD_WriteData(0x09);
    Int_LCD_WriteData(0x32);
    Int_LCD_WriteData(0x36);
    Int_LCD_WriteData(0x0F);
    /* 3.  Adjust Control 3 (F7h)  */
    /*Int_LCD_WriteCmd(0XF7);
   Int_LCD_WriteData(0xA9);
   Int_LCD_WriteData(0x51);
   Int_LCD_WriteData(0x2C);
   Int_LCD_WriteData(0x82);*/
    /* DSI write DCS command, use loose packet RGB 666 */

    /* 4. ��Դ����1*/
    Int_LCD_WriteCmd(0xC0);
    Int_LCD_WriteData(0x11); /* ��٤����ѹ */
    Int_LCD_WriteData(0x09); /* ��٤����ѹ */

    /* 5. ��Դ����2 */
    Int_LCD_WriteCmd(0xC1);
    Int_LCD_WriteData(0x02);
    Int_LCD_WriteData(0x03);

    /* 6. VCOM���� */
    Int_LCD_WriteCmd(0XC5);
    Int_LCD_WriteData(0x00);
    Int_LCD_WriteData(0x0A);
    Int_LCD_WriteData(0x80);

    /* 7. Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
    Int_LCD_WriteCmd(0xB1);
    Int_LCD_WriteData(0xB0);
    Int_LCD_WriteData(0x11);

    /* 8.  Display Inversion Control (B4h) ��������ѹ��ת�����ٵ�Ÿ��ţ�*/
    Int_LCD_WriteCmd(0xB4);
    Int_LCD_WriteData(0x02);

    /* 9.  Display Function Control (B6h)  */
    Int_LCD_WriteCmd(0xB6);
    Int_LCD_WriteData(0x0A);
    Int_LCD_WriteData(0xA2);

    /* 10. Entry Mode Set (B7h)  */
    Int_LCD_WriteCmd(0xB7);
    Int_LCD_WriteData(0xc6);

    /* 11. HS Lanes Control (BEh) */
    Int_LCD_WriteCmd(0xBE);
    Int_LCD_WriteData(0x00);
    Int_LCD_WriteData(0x04);

    /* 12.  Interface Pixel Format (3Ah) */
    Int_LCD_WriteCmd(0x3A);
    Int_LCD_WriteData(0x55); /* 0x55 : 16 bits/pixel  */

    /* 13. Sleep Out (11h) �ر�����ģʽ */
    Int_LCD_WriteCmd(0x11);

   

    /* 14. ������Ļ�����RGB */
    Int_LCD_WriteCmd(0x36);
    Int_LCD_WriteData(0x08);

    Delay_ms(120);

    /* 14. display on */
    Int_LCD_WriteCmd(0x29);
}

uint32_t Int_LCD_ReadID(void)
{
    uint32_t data = 0;
    // д����     Read display identification information (04h)
    // ��ȡ��ʾʶ����Ϣ(04h)
    Int_LCD_WriteCmd(0x04);

    Int_LCD_ReadData(); // ����Ϊ�������ݡ�

    data |= (Int_LCD_ReadData() & 0xFF) << 16; // LCD module��s manufacturer ID
    data |= (Int_LCD_ReadData() & 0xFF) << 8;  // LCD module/driver version ID.
    data |= (Int_LCD_ReadData() & 0xFF) << 0;  // LCD module/driver ID.

    return data;
}

void Int_LCD_SetArea(uint16_t x, uint16_t y, uint16_t wide, uint16_t high)
{
    Int_LCD_WriteCmd(0x2A);

    // �����е�ַ
    Int_LCD_WriteData(x >> 8);
    Int_LCD_WriteData(x & 0xFF);
    Int_LCD_WriteData((x + wide - 1) >> 8);
    Int_LCD_WriteData((x + wide - 1) & 0xFF);

    // �����е�ַ
    Int_LCD_WriteCmd(0x2B);
    Int_LCD_WriteData(y >> 8);
    Int_LCD_WriteData(y & 0xFF);
    Int_LCD_WriteData((y + high - 1) >> 8);
    Int_LCD_WriteData((y + high - 1) & 0xFF);
}

void Int_LCD_SetXY(uint16_t x, uint16_t y, uint16_t x_end, uint16_t y_end)
{
    Int_LCD_WriteCmd(0x2A);

    // �����е�ַ
    Int_LCD_WriteData(x >> 8);
    Int_LCD_WriteData(x & 0xFF);
    Int_LCD_WriteData((x_end) >> 8);
    Int_LCD_WriteData((x_end) & 0xFF);

    // �����е�ַ
    Int_LCD_WriteCmd(0x2B);
    Int_LCD_WriteData(y >> 8);
    Int_LCD_WriteData(y & 0xFF);
    Int_LCD_WriteData((y_end) >> 8);
    Int_LCD_WriteData((y_end) & 0xFF);
}

void Int_LCD_ClearAll(uint16_t color)
{
    // 1. ��������Ϊȫ��
    Int_LCD_SetArea(0, 0, 320, 480);

    // 2. ����д�Դ�����
    Int_LCD_WriteCmd(0x2C);

    // 3. ���������ص�����ͬ������ɫ
    for (uint32_t i = 0; i < 320 * 480; i++)
    {
        Int_LCD_WriteData(color);
    }
}

void Int_LCD_WriteAsciiChar(uint16_t x, uint16_t y, uint16_t h, uint8_t c, uint16_t fColor, uint16_t bColor)
{
    // ������������(���Ͻ�)
    Int_LCD_SetArea(x, y, h / 2, h);

    Int_LCD_WriteCmd(0x2C);

    uint8_t index = c - ' ';

    if (h == 16 || h == 12)
    {
        for (uint8_t i = 0; i < h; i++)
        {
            uint8_t rowByte = (h == 16 ? ascii_1608[index][i] : ascii_1206[index][i]);
            for (uint8_t j = 0; j < h / 2; j++)
            {
                if (rowByte & 0x01)
                {
                    Int_LCD_WriteData(fColor);
                }
                else
                {
                    Int_LCD_WriteData(bColor);
                }
                rowByte >>= 1;
            }
        }
    }
    else if (h == 24)
    {
        for (uint8_t i = 0; i < h * 2; i++)
        {
            uint8_t rowByte = ascii_2412[index][i];

            uint8_t jCount = i % 2 ? 4 : 8;

            for (uint8_t j = 0; j < jCount; j++)
            {
                if (rowByte & 0x01)
                {
                    Int_LCD_WriteData(fColor);
                }
                else
                {
                    Int_LCD_WriteData(bColor);
                }
                rowByte >>= 1;
            }
        }
    }
    else if (h == 32)
    {
        for (uint8_t i = 0; i < h * 2; i++)
        {
            uint8_t rowByte = ascii_3216[index][i];

            for (uint8_t j = 0; j < 8; j++)
            {
                if (rowByte & 0x01)
                {
                    Int_LCD_WriteData(fColor);
                }
                else
                {
                    Int_LCD_WriteData(bColor);
                }
                rowByte >>= 1;
            }
        }
    }
}

void Int_LCD_WriteAsciiString(uint16_t x, uint16_t y, uint16_t h, uint8_t *str, uint16_t fColor, uint16_t bColor)
{
    uint8_t i = 0;

    while (str[i] != '\0')
    {
        if (str[i] != '\n')
        {
            if ((x + h / 2) > DISPLAY_W)
            {
                // ����
                y += h;
                x = 0;
            }
            Int_LCD_WriteAsciiChar(x, y, h, str[i], fColor, bColor);
            x += h / 2; // �������ƶ�
        }
        else
        {
            y += h;
            x = 0;
        }
        i++;
    }
}

void Int_LCD_WriteChineseChar(uint16_t x, uint16_t y, uint16_t h, uint8_t index, uint16_t fColor, uint16_t bColor)
{
    Int_LCD_SetArea(x, y, h, h);

    Int_LCD_WriteCmd(0x2C);

    for (uint8_t i = 0; i < h / 8 * h; i++) //(h / 8)��ʾһ�����ݳ���ռ���ٸ��ֽ� * h ���� h(32/16) ��
    {
        uint8_t rowByte = chinese[index][i];
        for (uint8_t j = 0; j < 8; j++)
        {
            if (rowByte & 0x01)
            {
                Int_LCD_WriteData(fColor);
            }
            else
            {
                Int_LCD_WriteData(bColor);
            }
            rowByte >>= 1;
        }
    }
}

void Int_LCD_DisplayPicture(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const unsigned char *img, uint32_t len)
{
    Int_LCD_SetArea(x, y, width, height);

    Int_LCD_WriteCmd(0x2C);

    // printf("len = %d\n", len);

    for (uint64_t i = 0; i < len; i += 2)
    {
        uint16_t px = img[i] + (img[i + 1] << 8);
        Int_LCD_WriteData(px);
    }
}

void Int_LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t wide, uint16_t color)
{
    Int_LCD_SetArea(x, y, wide, wide);

    Int_LCD_WriteCmd(0x2C);

    for (uint8_t i = 0; i < wide * wide; i++)
    {
        Int_LCD_WriteData(color);
    }
}

void Int_LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t wide, uint16_t color)
{
    if (x1 == x2)
    {
        for (uint16_t y = y1; y < y2; y++)
        {
            Int_LCD_DrawPoint(x1, y, wide, color);
        }
        return;
    }
    // ����б�� �� �ؾ�
    double k = 1.0 * (y2 - y1) / (x2 - x1);
    double b = y1 - k * x1;

    // ����x1 > x2 �򽻻�ֵ б��Ϊ��ֵ
    uint16_t temp = 0;
    if (x1 > x2)
    {
        temp = x1;
        x1 = x2;
        x2 = temp;
    }

    for (uint16_t x = x1; x < x2; x++)
    {
        uint16_t y = (uint16_t)(k * x + b);
        Int_LCD_DrawPoint(x, y, wide, color);
    }
}

void Int_LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t wide, uint16_t color)
{
    if (x1 == x2 || y1 == y2)
    {
        Int_LCD_DrawLine(x1, y1, x2, y1, wide, color);
        return;
    }
    Int_LCD_DrawLine(x1, y1, x2, y1, wide, color);
    Int_LCD_DrawLine(x1, y1, x1, y2, wide, color);
    Int_LCD_DrawLine(x1, y2, x2, y2, wide, color);
    Int_LCD_DrawLine(x2, y1, x2, y2, wide, color);
}

void Int_LCD_DrawCircle(uint16_t xCenter, uint16_t yCenter, uint16_t r, uint16_t w, uint16_t color)
{

    for (uint16_t i = 0; i < 360; i++)
    {
        uint16_t x = xCenter + r * cos(i * PI / 180);
        uint16_t y = yCenter + r * sin(i * PI / 180);
        Int_LCD_DrawPoint(x, y, w, color);
    }
}

void Int_LCD_DrawFilledCircle(uint16_t xCenter, uint16_t yCenter, uint16_t r, uint16_t fColor, uint16_t bColor)
{
    uint16_t i  = 0;
    for (i = 0; i < r; i++)
    {
        Int_LCD_DrawCircle(xCenter,yCenter,i,1,bColor);
    }
    if (i == r)
    {
        Int_LCD_DrawCircle(xCenter,yCenter,i,1,fColor);
    }
}

void Int_LCD_color_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *color)
{
    uint16_t height,width;
    uint16_t i,j;
    (x1 > x2) ? (width = x1 -x2+1) : (width = x2 -x1+1) ;
    (y1 > y2)	? (height = y1 -y2+1): (height = y2 -y1+1 );
    Int_LCD_SetArea(x1,y1,width,height);
	
    Int_LCD_WriteCmd(0x2C);
    // uint32_t addr = 0;
    // for (i = 0; i < height; i++)
    // {
    //     HAL_DMA_Start_IT(&hdma_memtomem_dma2_channel4,(uint32_t)(color + addr),(uint32_t)LCD_ADDR_DATA,width);
    //     addr += width;
    // }
    
	uint32_t num = 0;
    for ( i = 0; i < height * width; i++)
    {    
        Int_LCD_WriteData(color[num]);
        num++;   
    }
    
}


void Int_LCD_color_lvgl(uint16_t x,uint16_t y,uint32_t color)
{
	Int_LCD_SetArea(x,y,1,1);
    Int_LCD_WriteCmd(0x2C);
    Int_LCD_WriteData(color);
	
}

void Int_LCD_Display_Inversion(bool b)
{
    if (b)
         Int_LCD_WriteCmd(0x21);  
    else
         Int_LCD_WriteCmd(0x20); 
} 


